﻿using System;
using System.Collections;
using System.Collections.Specialized;
using System.Linq;
using System.Windows;
using System.Windows.Media;

namespace AvalonDock
{
    public class FloatingDockablePane : DockablePane
    {
        #region Constants and Fields

        private readonly DockableContent _contentToTransfer;

        private readonly DockableFloatingWindow _floatingWindow;

        private readonly DockablePane _paneToTransfer;

        private int _arrayIndexPreviousPane = -1;

        private Pane _previousPane;

        #endregion

        #region Constructors and Destructors

        static FloatingDockablePane()
        {
            DefaultStyleKeyProperty.OverrideMetadata(
                typeof(FloatingDockablePane), new FrameworkPropertyMetadata(typeof(FloatingDockablePane)));
            //by design avoid style change

            ShowHeaderProperty.OverrideMetadata(typeof(FloatingDockablePane), new FrameworkPropertyMetadata(false));
        }

        internal FloatingDockablePane(DockableFloatingWindow floatingWindow, DockablePane paneToTransfer)
        {
            _floatingWindow = floatingWindow;
            _paneToTransfer = paneToTransfer;
        }

        internal FloatingDockablePane(DockableFloatingWindow floatingWindow, DockableContent contentToTransfer)
        {
            _floatingWindow = floatingWindow;
            _contentToTransfer = contentToTransfer;
        }

        #endregion

        #region Public Properties

        public DockableFloatingWindow FloatingWindow
        {
            get
            {
                return _floatingWindow;
            }
        }

        #endregion

        #region Public Methods and Operators

        public override void Dock()
        {
            DockableContent[] contentsToRedock = Items.Cast<DockableContent>().ToArray();

            foreach (DockableContent cntToRedock in contentsToRedock)
            {
                cntToRedock.Show();
            }

            base.Dock();
        }

        public override DockingManager GetManager()
        {
            return _floatingWindow.Manager;
        }

        #endregion

        #region Methods

        protected override void CheckItems(IList newItems)
        {
            if (Items.Count == 0 && FloatingWindow != null)
            {
                FloatingWindow.Close(true);
            }
        }

        protected override void OnInitialized(EventArgs e)
        {
            if (_paneToTransfer != null)
            {
                //setup window size
                var selectedContent = _paneToTransfer.SelectedItem as ManagedContent;
                if (selectedContent is DockableContent)
                {
                    _floatingWindow.SizeToContent = (selectedContent as DockableContent).FloatingWindowSizeToContent;
                }

                if (selectedContent != null && selectedContent.FloatingWindowSize.IsEmpty)
                {
                    selectedContent.FloatingWindowSize = new Size(
                        _paneToTransfer.ActualWidth, _paneToTransfer.ActualHeight);
                }

                if (selectedContent != null)
                {
                    _floatingWindow.Width = selectedContent.FloatingWindowSize.Width;
                    _floatingWindow.Height = selectedContent.FloatingWindowSize.Height;
                }
                else
                {
                    _floatingWindow.Width = _paneToTransfer.ActualWidth;
                    _floatingWindow.Height = _paneToTransfer.ActualHeight;
                }

                int selectedIndex = _paneToTransfer.SelectedIndex;

                //remove contents from container pane and insert in hosted pane
                while (_paneToTransfer.Items.Count > 0)
                {
                    var contentToTranser = (DockableContent)_paneToTransfer.Items[0];

                    contentToTranser.SaveCurrentStateAndPosition();

                    _paneToTransfer.RemoveContent(0);

                    //add content to my temporary pane
                    Items.Add(contentToTranser);

                    contentToTranser.SetStateToDockableWindow();
                }

                SelectedIndex = selectedIndex;

                ApplyTemplate();

                LayoutTransform = (MatrixTransform)_paneToTransfer.TansformToAncestor();
            }
            else if (_contentToTransfer != null)
            {
                //setup window size
                if (_contentToTransfer.FloatingWindowSize.IsEmpty)
                {
                    _contentToTransfer.FloatingWindowSize = new Size(
                        _contentToTransfer.ContainerPane.ActualWidth, _contentToTransfer.ContainerPane.ActualHeight);
                }

                _floatingWindow.Width = _contentToTransfer.FloatingWindowSize.Width;
                _floatingWindow.Height = _contentToTransfer.FloatingWindowSize.Height;

                //save current content position in container pane
                _previousPane = _contentToTransfer.ContainerPane;

                _arrayIndexPreviousPane = _previousPane.Items.IndexOf(_contentToTransfer);

                _contentToTransfer.SaveCurrentStateAndPosition();

                //remove content from container pane
                _contentToTransfer.ContainerPane.RemoveContent(_arrayIndexPreviousPane);

                //add content to this pane
                Items.Add(_contentToTransfer);

                SelectedIndex = 0;

                var originalDocumentPane = _previousPane as DocumentPane;
                if (originalDocumentPane != null)
                {
                    originalDocumentPane.CheckContentsEmpty();
                }

                _contentToTransfer.SetStateToDockableWindow();
                LayoutTransform = (MatrixTransform)_contentToTransfer.TansformToAncestor();
            }

            base.OnInitialized(e);
        }

        protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null)
            {
                e.NewItems.Cast<DockableContent>().ForEach(
                    c =>
                        {
                            if (c.State == DockableContentState.None)
                            {
                                if (FloatingWindow.IsDockableWindow)
                                {
                                    c.SetStateToDockableWindow();
                                }
                                else
                                {
                                    c.SetStateToFloatingWindow();
                                }
                            }
                        });
            }

            base.OnItemsChanged(e);
        }

        #endregion
    }
}